using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Xml.Schema;
using OpenComposite.Base.Collections;
using OpenComposite.EII.Designer.Workflow;
using OpenComposite.Mapper;

namespace OpenComposite.EII.Forms
{
	[ToolboxItem(false)]
	public partial class UCBinding : UserControl
	{
		#region Initializing
		public UCBinding(WorkflowController wfcontroller)
		{
			if ( wfcontroller == null )
				throw new ArgumentNullException("wfcontroller", "Missing workflow controller.");

			_wfcontroller = wfcontroller;
			_workflow = wfcontroller.Workflow;

			InitializeComponent();

			init();
		}
		private void init()
		{
			dgvBinding.AutoGenerateColumns = false;
		}
		#endregion

		#region Public Members
		public void Activate()
		{
			fillLogicalCapabilityList();
		}
		#endregion

		#region Protected Members


		#endregion

		#region Private Members

		#region Fields
		private Repository.Workflow _workflow;
		private WorkflowController _wfcontroller;
		private BindingListEx<BindingItem> _bindItems;
		#endregion

		#region Methods
		private void displayWorkflowInfos()
		{
			txtWorkflow.Text = _workflow.Name;
			//if ( _workflow.Type == OpenComposite.EII.Repository.WorkflowType.Business_Process ) {
			//    // workflow is business process
			//    tsbtnDeploy.Text = "Deploy / Update Business Process";
			//    tsbtnRedeploy.Text = "Redeploy Business Process";
			//} else if ( _workflow.Type == OpenComposite.EII.Repository.WorkflowType.Mashup ) {
			//    // workflow is mashup
			//    tsbtnDeploy.Text = "Deploy / Update Mashup";
			//    tsbtnRedeploy.Text = "Redeploy Mashup";
			//} else {
			//    // workflow is something else
			//    tsbtnDeploy.Text = "Deploy / Update Orchestration";
			//    tsbtnRedeploy.Text = "Redeploy Orchestration";
			//}
		}
		private void fillLogicalCapabilityList()
		{
			this.SuspendLayout();
			RepositoryService repSvc = _workflow.GetService(typeof(RepositoryService)) as RepositoryService;
			Debug.Assert(repSvc != null);

			if ( _bindItems == null ) {
				_bindItems = new BindingListEx<BindingItem>();
				dgvBinding.DataSource = _bindItems;
			} else {
				_bindItems.Clear();
			}
			int[] logactids = _workflow.ExtendedProperties.LogicalActivityIDs;
			if ( logactids != null ) {
				foreach ( int logactid in logactids ) {
					Repository.LogicalActivity la = repSvc.GetItem<Repository.LogicalActivity>(logactid);
					if ( la != null && !la.IsDeleted && ( la.VerbID > 0 || la.OperationID > 0 ) ) {
						la.Reload();
						if ( la.VerbID > 0 && la.LogicalMethodID <= 0 ) {
							Repository.Verb v = la.Verb;
							if ( v != null ) {
								la.BeginEdit();
								la.LogicalMethodID = v.DefaultLogicalMethodID;
								la.EndEdit(true);
							}
						}
						// add to items
						if ( la.LogicalMethodID > 0 ) {
							_bindItems.Add(new BindingItem(la, la.LogicalMethod));
						} else {
							_bindItems.Add(new BindingItem(la, null));
						}
					}
				}
			}
			this.ResumeLayout(true);
		}
		#region Old Methods
		//private void fillLogWMethCombo()
		//{
		//    RepositoryService rs = _workflow.GetService(typeof(RepositoryService)) as RepositoryService;
		//    Debug.Assert(rs != null);

		//    DataRow[] rows = Global.Data.GetRepositoryItemsOfDomainFolderTypeRecursive(
		//        Global.Status.CurrentDomainId, Repository.ItemType.LogicalWebMethod);

		//    colLogicalMethod.Items.Clear();
		//    if ( rows != null && rows.Length > 0 ) {
		//        foreach ( DataRow row in rows ) {
		//            if ( (int)row["type"] == (int)Repository.ItemType.LogicalWebMethod ) {
		//                Repository.LogicalWebMethod lwm =
		//                    rs.GetItem<Repository.LogicalWebMethod>((int)row["id"]);
		//                if ( lwm != null && !colLogicalMethod.Items.Contains(lwm) ) {
		//                    colLogicalMethod.Items.Add(lwm);
		//                }
		//            }
		//        }
		//    }
		//}
		#endregion
		private void doDeploy(bool update)
		{
			try {
				if ( _wfcontroller.Workflow != null && !string.IsNullOrEmpty(_wfcontroller.Workflow.Path) &&
					 Directory.Exists(_wfcontroller.Workflow.Path) ) {
					dlgSelectFolder.SelectedPath = _wfcontroller.Workflow.Path;
					if ( !dlgSelectFolder.SelectedPath.EndsWith("\\") )
						dlgSelectFolder.SelectedPath += "\\";

				}
			} catch {
			}
			if ( dlgSelectFolder.ShowDialog() != DialogResult.OK )
				return;

			_wfcontroller.DeployVSProjectCSharp(dlgSelectFolder.SelectedPath, update);
		}
		private BindingItem getSelectedItem()
		{
			BindingItem item = null;
			if ( dgvBinding.SelectedRows.Count > 0 ) {
				item = dgvBinding.SelectedRows[0].DataBoundItem as BindingItem;
			}
			Debug.Assert(item != null);
			return item;
		}
		private void doMapping(bool isInput)
		{
			BindingItem item = getSelectedItem();
			if ( item == null || item.LogicalActivity == null || item.HumanActivity == null ) return;
			Repository.WebMethod wmeth = item.LogicalActivity.GetWebMethod();
			if ( wmeth == null ) return;

			string connections, sXslt, codeMapping;
			XmlSchema xsdSource, xsdTarget;
			//XmlSchema xsdIn, xsdOut;
			FormMapping frm = new FormMapping();

			if ( isInput ) {
				sXslt = item.LogicalActivity.InputXslt == null ? null : item.LogicalActivity.InputXslt.InnerXml;
				connections = item.LogicalActivity.InputConnections;
				xsdSource = item.LogicalActivity.GetSubscribedCompoundXmlSchema();
				xsdTarget = wmeth.InputSchema;//item.LogicalActivity.InputBusinessObjectSchema;//_webMethod.InputSchema;
				codeMapping = item.LogicalActivity.ExtendedProperties.InputCodeMapping;
			} else {
				sXslt = item.LogicalActivity.OutputXslt == null ? null : item.LogicalActivity.OutputXslt.InnerXml;
				connections = item.LogicalActivity.OutputConnections;
				xsdSource = wmeth.OutputSchema;
				xsdTarget = item.LogicalActivity.OutputBusinessObjectSchema;
				codeMapping = item.LogicalActivity.ExtendedProperties.OutputCodeMapping;
			}
			frm.InitializeMapper(xsdSource, xsdTarget, sXslt, connections, codeMapping);
			//frm.HeaderText = new BusinessObject[] { item.LogicalActivity.InputBusinessObject, item.LogicalActivity.OutputBusinessObject }.GenerateCSharpCode();
			if ( frm.ShowDialog() == DialogResult.OK ) {
				XsltDocument xslt = frm.GetMapping(out connections);
				if ( isInput ) {
					item.LogicalActivity.InputConnections = connections;
					item.LogicalActivity.InputXslt = xslt;
				} else {
					item.LogicalActivity.OutputConnections = connections;
					item.LogicalActivity.OutputXslt = xslt;
				}
				item.LogicalActivity.Save();
				_wfcontroller.IsChanged = true;
			}
		}
		#endregion

		#region Event Handlers
		private void FormBinding_Load(object sender, EventArgs e)
		{
			displayWorkflowInfos();
			//fillLogicalCapabilityList();
		}

		private void tsbtnDeploy_Click(object sender, EventArgs e)
		{
			doDeploy(true);
		}
		private void tsbtnRedeploy_Click(object sender, EventArgs e)
		{
			//DialogResult result =
			//    MessageBox.Show("All external changes will be deleted." + Environment.NewLine + Environment.NewLine +
			//                    "Do you want to continue?", tsbtnRedeploy.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
			//if ( result == DialogResult.Yes ) {
			//    doDeploy(false);
			//}
		}

		private void dgvBinding_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
		{
			//DataTable dt = Global.Data.GetRepositoryItemsOfDomainFolderType(
			//    Global.Status.CurrentDomainId, Repository.ItemType.LogicalWebMethod);

		}
		private void dgvBinding_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e)
		{
			if ( e.RowIndex < 0 || e.RowIndex >= _bindItems.Count ) return;

			dgvBinding.Rows[e.RowIndex].Selected = true;
			BindingItem item = getSelectedItem();

			bool isHA = ( item != null && item.HumanActivity != null );
			miHAProperties.Visible = isHA;
			sepHAProps.Visible = isHA;
			if ( e.ColumnIndex == colCapability.Index || e.ColumnIndex == colLogicalMethod.Index ) {
				e.ContextMenuStrip = contextLogWMeth;
			}
		}
		private void dgvBinding_CellClick(object sender, DataGridViewCellEventArgs e)
		{
			if ( e.RowIndex < 0 || e.RowIndex >= _bindItems.Count ) return;

			dgvBinding.Rows[e.RowIndex].Selected = true;
			BindingItem item = getSelectedItem();

			bool isHA = ( item != null && item.HumanActivity != null );
			miHAProperties.Visible = isHA;
			sepHAProps.Visible = isHA;

			if ( e.ColumnIndex == colLogicalMethod.Index ) {
				Rectangle rect = dgvBinding.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false);
				contextLogWMeth.Show(dgvBinding, rect.Left, rect.Bottom);
			}
		}

		private void miSelectLogWMeth_Click(object sender, EventArgs e)
		{
			BindingItem item = getSelectedItem();

			int inputboid = ( item.LogicalActivity.InputBusinessObject == null ?
								-1 : item.LogicalActivity.InputBusinessObject.ID );
			int outputboid = ( item.LogicalActivity.OutputBusinessObject == null ?
								-1 : item.LogicalActivity.OutputBusinessObject.ID );

			FormSelectLogicalMethod frm = new FormSelectLogicalMethod(_workflow, inputboid, outputboid);
			frm.DomainID = Global.Status.CurrentDomainId;
			frm.RepositoryID = Global.Status.CurrentRepositoryId;
			frm.MultiSelect = false;
			frm.SelectedItem = item.LogicalWebMethod;
			if ( frm.ShowDialog() == DialogResult.OK ) {
				item.LogicalWebMethod = frm.SelectedItem as Repository.LogicalWebMethod;
				item.LogicalActivity.LogicalMethod = item.LogicalWebMethod;
				item.LogicalActivity.Save();
				dgvBinding.Refresh();
				_wfcontroller.IsChanged = true;
			}
		}
		private void miCreateLogWMeth_Click(object sender, EventArgs e)
		{
			BindingItem item = getSelectedItem();
			RepositoryService rs = _workflow.GetService(typeof(RepositoryService)) as RepositoryService;
			Debug.Assert(rs != null);

			Repository.IRepositoryItem parentNew;
			Repository.IRepositoryItem parent = null;
			Repository.LogicalWebMethod logwm =
				rs.GetNewItem<Repository.LogicalWebMethod>(false, ref parent);

			this.Refresh();
			if ( logwm == null ) return;

			int domainId = Global.Status.CurrentDomainId;
			int folderId = -1;
			if ( parent != null && parent.RepositoryItemType == OpenComposite.EII.Repository.ItemType.GenericFolder )
				folderId = parent.ID;
			if ( logwm.ShowNewItemFormEx(Global.Status.CurrentRepositoryId, false, parent,
					ref domainId, out parentNew,
					item.LogicalActivity.InputBusinessObject, item.LogicalActivity.OutputBusinessObject)
				 != DialogResult.OK ) {
				return;
			}

			Global.Data.AddRepositoryItemToDomainFolder(Global.Status.CurrentDomainId, logwm);

			item.LogicalWebMethod = logwm;
			item.LogicalActivity.LogicalMethod = logwm;
			item.LogicalActivity.Save();
			dgvBinding.Refresh();
			_wfcontroller.IsChanged = true;
		}
		private void miRemoveLogWMeth_Click(object sender, EventArgs e)
		{
			BindingItem item = getSelectedItem();
			item.LogicalWebMethod = null;
			item.HumanActivity = null;
			item.LogicalActivity.LogicalMethod = null;
			item.LogicalActivity.HumanActivityID = -1;
			item.LogicalActivity.WebMethodID = -1;
			item.LogicalActivity.WebServiceID = -1;
			item.LogicalActivity.Save();
			dgvBinding.Refresh();
			_wfcontroller.IsChanged = true;
		}

		private void miHAProperties_Click(object sender, EventArgs e)
		{
			BindingItem item = getSelectedItem();
			if ( item.LogicalActivity != null ) {
				FormHumanTaskProperties frm = new FormHumanTaskProperties(item.LogicalActivity, _workflow);
				if ( frm.ShowDialog() == DialogResult.OK ) {
					_wfcontroller.IsChanged = true;
				}
			}
		}
		private void miHAInputMapping_Click(object sender, EventArgs e)
		{
			BindingItem item = getSelectedItem();
			doMapping(true);
		}
		private void miHAOutputMapping_Click(object sender, EventArgs e)
		{
			BindingItem item = getSelectedItem();
			doMapping(false);
		}
		private void miSelectHumanActivity_Click(object sender, EventArgs e)
		{
			BindingItem item = getSelectedItem();
			if ( item == null || item.LogicalActivity == null ) return;

			FormSelectRepositoryEx frm = new FormSelectRepositoryEx(_workflow);
			frm.DomainID = Global.Status.CurrentDomainId;
			frm.RepositoryID = Global.Status.CurrentRepositoryId;
			frm.MultiSelect = false;
			frm.AllowedTypes = new Repository.ItemType[] { Repository.ItemType.HumanActivity };
			if ( frm.ShowDialog() == DialogResult.OK ) {
				Repository.HumanActivity hact = frm.SelectedItem as Repository.HumanActivity;
				if ( hact != null ) {
					Repository.WebService ws = hact.WebService;
					if ( ws != null && item.LogicalActivity.HumanActivityID != hact.ID ) {
						item.LogicalActivity.WebServiceID = ws.ID;
						BindingListEx<Repository.WebMethod> wms = ws.GetWebMethods();
						if ( wms.Count > 0 ) {
							item.LogicalActivity.WebMethodID = wms[0].ID;
						}
						item.LogicalActivity.HumanActivityID = hact.ID;
						item.LogicalActivity.LogicalMethod = null;
						item.LogicalActivity.Save();
					}
					item.HumanActivity = hact;
					item.LogicalWebMethod = null;
					dgvBinding.Refresh();
				}
			}
		}

		#endregion

		#endregion

		#region Private Class: BindingItem
		private class BindingItem
		{
			public BindingItem(Repository.LogicalActivity logact, Repository.LogicalWebMethod logwmeth)
			{
				_logact = logact;
				_logwmeth = logwmeth;

				if ( logact != null && logwmeth != null ) {
					_hact = logwmeth.GetAssignedHumanActivity();
				}
			}

			private Repository.LogicalActivity _logact = null;
			private Repository.LogicalWebMethod _logwmeth = null;
			private Repository.HumanActivity _hact = null;

			public Repository.LogicalActivity LogicalActivity
			{
				get { return _logact; }
				set { _logact = value; }
			}
			public Repository.LogicalWebMethod LogicalWebMethod
			{
				get { return _logwmeth; }
				set { _logwmeth = value; }
			}
			public Repository.HumanActivity HumanActivity
			{
				get { return _hact; }
				set { _hact = value; }
			}

			public string LogicalActivityName
			{
				get
				{
					string s = "";
					if ( this.LogicalActivity != null ) {
						Repository.Verb v = this.LogicalActivity.Verb;
						if ( v != null ) {
							s = v.Name;
						} else {
							s = this.LogicalActivity.Name;
						}
					}
					return s;
				}
			}
			public string LogicalWebMethodName
			{
				get
				{
					if ( this.LogicalWebMethod != null ) {
						return this.LogicalWebMethod.Name;
					} else {
						return "";
					}
				}
			}
		}
		#endregion

	}
}
